package com.soundplus.app.shp04.Activity;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

import androidx.appcompat.app.AppCompatActivity;

import com.example.sppmode.Common.AllParam;
import com.example.sppmode.Common.DataConfig;
import com.example.sppmode.Common.PairedDeviceInfo;
import com.example.sppmode.Common.Utils;
import com.example.sppmode.DataProtocol.CommandImageInfo;
import com.example.sppmode.DataProtocol.CommandInfo;
import com.soundplus.app.shp04.DeviceConnectMgr.DevConnEventListener;
import com.soundplus.app.shp04.DeviceConnectMgr.DevConnMgr;
import com.soundplus.app.shp04.DeviceConnectMgr.DevConnService;
import com.soundplus.app.shp04.R;
import com.soundplus.app.shp04.databinding.ActivityMainBinding;

import java.util.Locale;

public class MainActivity extends AppCompatActivity {

    private static final int MSGID_DEV_CONNECT = 1;
    private static final int MSGID_DEV_CONN_STATE_CHANGED = MSGID_DEV_CONNECT + 1;
    private static final int MSGID_RECV_CONTENT_UPDATE = MSGID_DEV_CONN_STATE_CHANGED + 1;
    private static final int MSGID_BAT_INFO_UPDATE = MSGID_RECV_CONTENT_UPDATE + 1;
    private static final int MSGID_IMAGE_REPORT_IMAGE_INFO = MSGID_BAT_INFO_UPDATE + 1;
    private static final int MSGID_IMAGE_REPORT_IMAGE_DATA = MSGID_IMAGE_REPORT_IMAGE_INFO + 1;

    private Context context;
    private ActivityMainBinding binding;
    private MyHandler myHandler;
    private DevConnMgr devConnMgr;
    private StringBuilder configStrBuilder;
    private PairedDeviceInfo pairedDevice = null;
    private final CommandImageInfo recvImageInfo = new CommandImageInfo();
    private int imageRecvLen = 0;
    private int imageRecvPackIndex = 0;
    private byte[] imageData = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        context = this;
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        setSupportActionBar(binding.toolbar);

        AllParam.getAppInfo().setFirstRunning(false);
        myHandler = new MyHandler(context, getMainLooper());
        devConnMgr = DevConnMgr.getInstance();

        initView();
    }

    @Override
    protected void onResume() {
        super.onResume();
        initData();
        updateDevConnStatus(devConnMgr.getConnectStatus());
        updateViewImageInfo();
        devConnMgr.addDevConnEventListener(devConnEventListener);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        devConnMgr.destroy(context.getApplicationContext());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            Intent intent = new Intent(MainActivity.this, SettingActivity.class);
            startActivity(intent);

            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private void initView() {
        configStrBuilder = new StringBuilder();
// 加号按键，获取已连接设备
        binding.mainContent.ivAddDev.setOnClickListener(view -> {
            Intent intent = null;
            if (AllParam.getConnProtocolType() == DevConnMgr.CONN_PROTOCOL_BLE)
                intent = new Intent(MainActivity.this, LeDeviceScanActivity.class);
            else if (AllParam.getConnProtocolType() == DataConfig.CONN_PROTOCOL_SPP)
                intent = new Intent(MainActivity.this, SppDeviceScanActivity.class);
            else
                return;

            startActivity(intent);
        });
// 发送按键，发送键值
        binding.mainContent.btnSendKeyValue.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendCommandKeyValue();
            }
        });
    }

    private void initData() {
        pairedDevice = AllParam.getPairedDevInfo().getLastConnDevice();

        if (pairedDevice.isValidDevice()) {
            updateViewDevName(pairedDevice.getName());
            updateDevConnStatus(devConnMgr.getConnectStatus());
            myHandler.sendMessage(myHandler.obtainMessage(MSGID_DEV_CONNECT));
        } else {
            binding.mainContent.tvDevName.setText(R.string.dev_name);
            binding.mainContent.tvDevName.setTextColor(Color.GRAY);
        }
    }

    private class MyHandler extends Handler {
        Context context;
        Looper looper;

        public MyHandler(Context context, Looper looper) {
            super(looper);
            this.context = context;
            this.looper = looper;
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSGID_DEV_CONNECT:
                    if (pairedDevice.isValidDevice()) {
                        if (devConnMgr.getConnectStatus() != DataConfig.STATE_CONNECTED) {
                            devConnMgr.connectDevice(DataConfig.CONN_PROTOCOL_TYPE_SPP, pairedDevice.getMacAddr());
                            myHandler.sendMessageDelayed(myHandler.obtainMessage(MSGID_DEV_CONNECT), 5000);
                        }
                    }
                    break;

                case MSGID_DEV_CONN_STATE_CHANGED:
                    updateDevConnStatus(msg.arg1);
                    if (msg.arg1 != DataConfig.STATE_CONNECTED) {
                        myHandler.sendMessageDelayed(myHandler.obtainMessage(MSGID_DEV_CONNECT), 1000);
                    }
                    break;

                case MSGID_RECV_CONTENT_UPDATE:
                    updateViewRecvContent((String) msg.obj);
                    break;

                case MSGID_BAT_INFO_UPDATE:
                    updateViewBatteryInfo(msg.arg1);
                    break;

                case MSGID_IMAGE_REPORT_IMAGE_INFO:
                    updateViewImageInfo();
                    showImage();
                    break;

                case MSGID_IMAGE_REPORT_IMAGE_DATA:
                    updateViewImageInfo();
                    if (imageRecvLen >= recvImageInfo.getImageSize() || imageRecvPackIndex >= recvImageInfo.getImagePackCnt()) {
                        showImage();
                    }
                    break;
            }
        }

    }

    private DevConnEventListener devConnEventListener = new DevConnEventListener() {
        @Override
        public void onConnStatusChanged(int status) {
            myHandler.sendMessage(myHandler.obtainMessage(MSGID_DEV_CONN_STATE_CHANGED, status, 0));
        }

        @Override
        public boolean onDataReceived(byte[] data) {
            return false;
        }

        @Override
        public void onCommandReceived(CommandInfo commandInfo) {
            dealCommand(commandInfo);
        }
    };


    private void updateViewDevName(String name) {
        binding.mainContent.tvDevName.setText(name);
    }

    private void updateViewBatteryInfo(int percent) {
        binding.mainContent.tvBatPercentValue.setText("" + percent + "%");
    }

    private void updateViewRecvContent(String content) {
        String timeStr = Utils.covertMillisecond2TimeStr(System.currentTimeMillis());
        configStrBuilder.insert(0, timeStr + ": " + content + "\n");
        binding.mainContent.etRecvContent.setText(configStrBuilder.toString());
    }

    private void updateDevConnStatus(int status) {
        if (status == DataConfig.STATE_CONNECTED) {
            binding.mainContent.tvDevName.setTextColor(Color.GREEN);
        } else {
            binding.mainContent.tvDevName.setTextColor(Color.BLACK);
        }
    }

    private void updateBatteryInfo(int percent) {
        myHandler.sendMessage(myHandler.obtainMessage(MSGID_BAT_INFO_UPDATE, percent, 0));
    }

    private void updateRecognizedTag(int tag) {
        String str = "TAG = " + tag;
        myHandler.sendMessage(myHandler.obtainMessage(MSGID_RECV_CONTENT_UPDATE, str));
    }

    private void updateViewImageInfo() {
        binding.mainContent.tvImageWh.setText(String.format(Locale.getDefault(), "%dx%d", recvImageInfo.getImageWidth(), recvImageInfo.getImageHeight()));
        binding.mainContent.tvImageSize.setText("" + recvImageInfo.getImageSize());
        binding.mainContent.tvImageRecv.setText("" + imageRecvLen);
    }

    private void showImage() {

        if(false) {
            byte[] bitmapData = new byte[tempImageData.length];
            for (int i = 0; i < bitmapData.length; i++) {
                bitmapData[i] = (byte) tempImageData[i];
            }
            Bitmap bitmap = convertByteToBitmap(bitmapData);
            binding.mainContent.ivImgRecived.setImageBitmap(bitmap);
        } else {
            if(imageData != null) {
                Bitmap bitmap = convertByteToBitmap(imageData);
                binding.mainContent.ivImgRecived.setImageBitmap(bitmap);
            }
        }
    }

    private void dealCommand(CommandInfo cmd) {
        switch (cmd.getCommandID()) {
            case CommandInfo.CMDID_BAT_INFO_SYNC:
                if (cmd.getErrCode() == CommandInfo.ERROR_CODE_NONE) {
                    updateBatteryInfo(cmd.getBatteryPercent());
                }
                break;

            case CommandInfo.CMDID_RECOGNIZED_TAG_REPORT:
                if (cmd.getErrCode() == CommandInfo.ERROR_CODE_NONE) {
                    updateBatteryInfo(cmd.getBatteryPercent());
                    updateRecognizedTag(cmd.getRecognizedTag());
                }
                break;

            case CommandInfo.CMDID_IMAGE_REPORT_IMAGE_INFO:
                if (cmd.getErrCode() == CommandInfo.ERROR_CODE_NONE) {
                    CommandImageInfo imageInfo = cmd.getCommandImageInfo();
                    recvImageInfo.setImageWidth(imageInfo.getImageWidth());
                    recvImageInfo.setImageHeight(imageInfo.getImageHeight());
                    recvImageInfo.setImageSize(imageInfo.getImageSize());
                    recvImageInfo.setImagePackCnt(imageInfo.getImagePackCnt());
                    imageRecvLen = 0;
                    imageData = new byte[imageInfo.getImageSize()];
                    myHandler.sendMessage(myHandler.obtainMessage(MSGID_IMAGE_REPORT_IMAGE_INFO));
                }
                break;

            case CommandInfo.CMDID_IMAGE_REPORT_IMAGE_DATA:
                if (cmd.getErrCode() == CommandInfo.ERROR_CODE_NONE) {
                    CommandImageInfo imageInfo = cmd.getCommandImageInfo();
                    imageRecvPackIndex = imageInfo.getImagePackIndex();
                    int imgPackSize = imageInfo.getImagePackSize();
                    byte[] imgData = imageInfo.getImagePackData();

                    if (imgPackSize > 0 && imgData != null && imageData != null) {
                        if (imageRecvLen + imgPackSize <= imageData.length) {
                            System.arraycopy(imgData, 0, imageData, imageRecvLen, imgPackSize);
                            imageRecvLen += imageInfo.getImagePackSize();
                        }
                    }
                    myHandler.sendMessage(myHandler.obtainMessage(MSGID_IMAGE_REPORT_IMAGE_DATA));

                }
                break;
        }
    }

    private void sendCommandKeyValue() {
        String strValue = binding.mainContent.etKeyValue.getText().toString();
        int keyValue = Integer.valueOf(strValue);

        byte[] data = new byte[1];
        data[0] = (byte) keyValue;

        CommandInfo cmd = new CommandInfo();
        cmd.setFrom(CommandInfo.DEVICE_APP);
        cmd.setTo(CommandInfo.DEVICE_MCU);
        cmd.setCommandID(CommandInfo.CMDID_KEY_VALUE_ISSUE);
        cmd.setCmdData(data);
        devConnMgr.sendCommandData(cmd);
    }

    private int[] tempImageData = new int[]{
            0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52,
            0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x18, 0x08, 0x02, 0x00, 0x00, 0x00, 0x80, 0xD7, 0xC1,
            0x91, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xAE, 0xCE, 0x1C, 0xE9, 0x00, 0x00,
            0x00, 0x04, 0x67, 0x41, 0x4D, 0x41, 0x00, 0x00, 0xB1, 0x8F, 0x0B, 0xFC, 0x61, 0x05, 0x00, 0x00,
            0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x12, 0x74, 0x00, 0x00, 0x12, 0x74, 0x01, 0xDE,
            0x66, 0x1F, 0x78, 0x00, 0x00, 0x00, 0x3E, 0x49, 0x44, 0x41, 0x54, 0x48, 0x4B, 0x63, 0xF8, 0x4F,
            0x3D, 0x30, 0x12, 0xCD, 0x62, 0x00, 0x03, 0x28, 0x07, 0x1B, 0xC0, 0xA3, 0x60, 0xD4, 0x2C, 0x2C,
            0x00, 0x8F, 0x82, 0xA1, 0x65, 0x16, 0x41, 0x00, 0x55, 0x8D, 0x0A, 0x68, 0x6F, 0x16, 0x94, 0x83,
            0x0D, 0xE0, 0x51, 0x30, 0x6A, 0x16, 0x16, 0x80, 0x47, 0xC1, 0x50, 0x31, 0x8B, 0x12, 0x30, 0xFC,
            0xCD, 0xFA, 0xFF, 0x1F, 0x00, 0xEA, 0xDA, 0x0C, 0x49, 0xDF, 0x18, 0x49, 0x76, 0x00, 0x00, 0x00,
            0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82
    };

    private static Bitmap convertByteToBitmap(byte[] data){
        return BitmapFactory.decodeByteArray(data, 0, data.length);
    }
}